package com.dbms.execution.execution;

import com.dbms.catalog.Catalog;
import com.dbms.common.Schema;
import com.dbms.common.Tuple;
import com.dbms.execution.plan.PlanNode;
import com.dbms.storage.BufferPoolManager;
import com.dbms.storage.Page;
import com.dbms.storage.TablePage;

import java.io.IOException;

/**
 * RevokeExecutor (收回权限执行器) 负责执行 REVOKE 命令的计划。
 * 它的工作方式是顺序扫描系统权限表 `_privileges_`，
 * 查找与命令中指定的用户、表和权限完全匹配的记录，然后将其删除。
 */
public class RevokeExecutor implements Executor {

    private final Catalog catalog;
    private final BufferPoolManager bufferPoolManager;
    private final String privilege; // 要收回的权限 (e.g., "SELECT")
    private final String tableName; // 目标表名
    private final String userName;  // 目标用户名
    private boolean hasExecuted = false;

    public RevokeExecutor(Catalog catalog, BufferPoolManager bufferPoolManager, String privilege, String tableName, String userName) {
        this.catalog = catalog;
        this.bufferPoolManager = bufferPoolManager;
        this.privilege = privilege;
        this.tableName = tableName;
        this.userName = userName;
    }

    @Override
    public void open() {
        hasExecuted = false;
    }

    @Override
    public Tuple next() {
        if (hasExecuted) {
            return null;
        }

        // 1. 获取系统权限表的元数据
        Catalog.TableMetadata privilegeInfo = catalog.getTable("_privileges_");
        if (privilegeInfo == null) {
            throw new RuntimeException("System error: _privileges_ table not found.");
        }

        // 2. 从根页面开始，遍历权限表的所有页面
        int currentPageId = privilegeInfo.rootPageId;
        Page currentPage = null;
        boolean permissionFoundAndRevoked = false;

        try {
            while (currentPageId != TablePage.INVALID_PAGE_ID && !permissionFoundAndRevoked) {
                currentPage = bufferPoolManager.fetchPage(currentPageId);
                if (currentPage == null) break;

                // 加写锁，因为我们可能要删除记录
                currentPage.wLock();

                try {
                    TablePage tablePage = new TablePage(currentPage);
                    // 遍历页面上的所有槽位
                    for (int slotNum = 0; slotNum < tablePage.getSlotCount(); slotNum++) {
                        byte[] tupleData = tablePage.getTuple(slotNum);
                        if (tupleData == null) continue; // 跳过空槽位

                        // 反序列化元组以读取权限信息
                        Tuple tuple = new Tuple(tupleData, privilegeInfo.schema);
                        // 假设 Schema 为 (user_name, table_name, privilege)
                        String grantedUser = (String) tuple.getValue(0);
                        String grantedTable = (String) tuple.getValue(1);
                        String grantedPriv = (String) tuple.getValue(2);

                        // 检查用户名、表名和权限是否都匹配
                        if (grantedUser.equalsIgnoreCase(userName) &&
                                grantedTable.equalsIgnoreCase(tableName) &&
                                grantedPriv.equalsIgnoreCase(privilege)) {

                            // 找到了匹配的权限记录，执行删除
                            tablePage.deleteTuple(slotNum);
                            permissionFoundAndRevoked = true;
                            break; // 假设权限记录是唯一的，找到后即可停止
                        }
                    }
                } finally {
                    currentPage.wUnlock(); // 释放锁
                    // 解钉页面，如果执行了删除，则标记为脏页
                    bufferPoolManager.unpinPage(currentPageId, permissionFoundAndRevoked);
                }

                // 如果在本页未找到，则移动到下一页
                if (!permissionFoundAndRevoked) {
                    currentPageId = new TablePage(currentPage).getNextPageId();
                }
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to revoke privilege", e);
        } finally {
            hasExecuted = true;
        }

        // 如果遍历完所有页面后仍未找到匹配的权限，则打印警告
        if (!permissionFoundAndRevoked) {
            System.out.println("Warning: Privilege not found or already revoked. Nothing to do.");
        }

        return null; // DCL 操作不返回元组
    }

    @Override
    public void close() {}

    @Override
    public Schema getSchema() {
        return null;
    }

    @Override
    public PlanNode getPlanNode() {
        return null;
    }
}